package com.register.client.start;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.register.client.domian.*;
import com.register.client.utils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * 负责发送各种http请求组件
 */
@Component
public class HttpSender {

    public static final Logger log = LoggerFactory.getLogger(HttpSender.class);
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ServerInfomation serverInfomation;

    /**
     * 注册
     *
     * @param registerRequest
     * @return
     */
    Response register(RegisterRequest registerRequest) {
        Response response = null;
        try {
            String url = "http://" + serverInfomation.getAddress() + "/register/initRegister";
            //网络组件, 远程调用
            response = restTemplate.postForObject(url, registerRequest, Response.class);
        } catch (RestClientException e) {
            log.error("服务注册失败,server出现异常", e);
            return Response.FAILE;
        }
        return response;
    }

    /**
     * 发送心跳
     *
     * @param heartBeat
     * @return
     */
    Response heartBeat(HeartBeat heartBeat
    ) {
        //网络组件, 远程调用
        Response response = null;
        try {
            String url = "http://" + serverInfomation.getAddress() + "/query/heartBeat";
            response = restTemplate.postForObject(url, heartBeat, Response.class);
        } catch (RestClientException e) {
            log.error("服务注册失败,server出现异常", e);
            return Response.FAILE;
        }
        return response;
    }

    /**
     * 拉取注册表
     *
     * @return
     */
    public Map<String, Map<String, ClientServiceInstance>> fetchServiceRegistry() {

        //网络组件, 远程调用
        Map<String, Map<String, ClientServiceInstance>> response = null;
        try {
            String url = "http://" + serverInfomation.getAddress() + "/query/fetchServiceRegistry";
            response = restTemplate.getForObject(url, Map.class);
            return response;
        } catch (RestClientException e) {
            log.error("service服务发生异常[{}]", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            return null;
        }
    }

    /**
     * client下线,通知server去除本实例
     */
    public void noticeServerMoveInstance(RegisterRequest registerRequest) {
        String url = "http://" + serverInfomation.getAddress() + "/submit/extirpateInstance";
        Response response = restTemplate.postForObject(url, registerRequest, Response.class);
        log.info("client服务下线成功[{}]",response.getCode());
    }

    /**
     * client拉取增量注册表
     */
    public Map<String, Map<String, ClientServiceInstance>> fetchDeltaServiceRegistry() {
        //网络组件, 远程调用
        Map<String, Map<String, ClientServiceInstance>> response = null;
        try {
            String url = "http://" + serverInfomation.getAddress() + "/query/fetchDeltaServiceRegistry";
            Map template = restTemplate.getForObject(url, Map.class);
            response = mapToObject(template);
            return response;
        } catch (RestClientException e) {
            log.error("service服务发生异常[{}]", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            return null;
        }
    }

    private Map<String, Map<String, ClientServiceInstance>> mapToObject(Map response)  {
        Map<String, Map<String, ClientServiceInstance>> doMap = new HashMap<>();

        if (response != null) {
            Set<String> keys = response.keySet();
            for (String serviceInstanceName : keys) {
                LinkedHashMap  serviceInstanceMap= (LinkedHashMap) response.get(serviceInstanceName);
                Set<String> instanceIds = serviceInstanceMap.keySet();
                Map<String,ClientServiceInstance> clientServiceInstanceMap = new HashMap<>();
                for (String instanceId : instanceIds) {
                    LinkedHashMap linkedHashMap = (LinkedHashMap) serviceInstanceMap.get(instanceId);
                    ClientServiceInstance clientServiceInstance = null;
                    try {
                        clientServiceInstance = BeanUtils.mapToObejct(linkedHashMap, ClientServiceInstance.class);
                    } catch (Exception e) {
                        log.error("拉取增量注册表转化失败",e);
                    }
                    clientServiceInstanceMap.put(instanceId,clientServiceInstance);
                }
                doMap.put(serviceInstanceName,clientServiceInstanceMap);
            }
        }
        return doMap;
    }
}
